# -*- coding: utf-8 -*-
import scrapy
from scrapy.contrib.spiders import Rule
from scrapy.contrib.linkextractors import LinkExtractor, re
from hexunblog.bloom.bloom import BloomFilter
from hexunblog.service.article_service import ArticleInfoService
from hexunblog.utils.header_util import HeaderUtil


class SpiderHexunblogSpider(scrapy.Spider):
    name = 'spider_hexunblog'
    allowed_domains = ['hexun.com']
    start_urls = [
        'http://blog.hexun.com/',
        'http://blog.hexun.com/group/shehui.html',
        'http://blog.hexun.com/group/life.html',
        'http://blog.hexun.com/group/blogstars.html',
        'http://blog.hexun.com/finance.htm',
        'http://blog.hexun.com/group/bojingtou.html',
        'http://f.blog.hexun.com/',
    ]

    _rules = [
        # 规则匹配 域名'hexun.com'
        Rule(
            LinkExtractor(
                allow=(),
                allow_domains=allowed_domains,
            )
        )
    ]

    # 实例化一个布隆过滤器
    bf = BloomFilter(0.001, 10000000)

    # 参考了CrawlSpider的设计，使用Rule从网页中分析所有的URL
    # 分析当前网页内的所有URL，进行过滤网页中的样式表的引用：.css
    # 使用布隆过滤器对URL进行过滤
    def seen_url(self, response):
        seen_urls = []
        for n, rule in enumerate(self._rules):
            links = [lnk for lnk in rule.link_extractor.extract_links(response)]
            for link in links:
                url = link.url
                if not self.bf.is_element_exist(url):
                    if not url.endswith(".css") \
                            and url.find("blog.hexun.com") >= 0 \
                            and url.find("login.aspx") <= 0 \
                            and url.find("robots.txt") <= 0:
                        self.bf.insert_element(url)
                        seen_urls.append(url)
        return seen_urls

    # 分析页面内容
    # 如果页面上有 <div class="p-entry">或者<div class="entry"> 这个元素，那么 说明是博文页面，否则就不是
    def parse(self, response):
        # 先分析页面的内容，判断是博文页面，还是其他页面
        articleblogtext_node_list = response.xpath(".//div[@class='ArticleBlogText']")
        if articleblogtext_node_list:
            blog_url = response.meta['blog_url']
            item = ArticleInfoService.compose_article_item(response, blog_url)
            if item["article_id"] and item["blog_id"]:
                yield item
                # 再去获取点击量和评论数
                click_url = "http://click.tool.hexun.com/click.aspx?articleid=" + item["article_id"] + "&blogid=" + \
                            item["blog_id"]
                yield scrapy.Request(click_url, callback=self.analyse_click_count,
                                     headers=HeaderUtil.get_comment_request_header(blog_url, click_url),
                                     meta={'blog_url': blog_url, 'article_id': item["article_id"]}
                                     )
        # 继续获取当前页面上所有的URL
        seen_urls = self.seen_url(response)
        for url in seen_urls:
            yield scrapy.Request(url, callback=self.parse,
                                 headers=HeaderUtil.get_common_request_header(url),
                                 meta={'blog_url': url}
                                 )

    # 博文的点击数量和评论数量需要进一步进行分析
    # 此时博文数据已经存储，分析完成后，需要更新博文信息
    def analyse_click_count(self, response):
        article_id = response.meta['article_id']
        html_content = response.body_as_unicode()
        pattern = re.compile(r'.*?.innerHTML = (.*?);.*?')
        rst = re.findall(pattern, html_content)
        item = None
        if len(rst) == 2:
            item = ArticleInfoService.compose_article_count(article_id, rst[0], rst[1])
        elif len(rst) == 1:
            item = ArticleInfoService.compose_article_count(article_id, rst[0], 0)
        if item:
            yield item


